package com.bauer.module.framework.dubbo;

import com.alibaba.fastjson.JSON;

import org.apache.dubbo.rpc.Filter;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcContext;
import org.apache.dubbo.rpc.RpcException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @Author ：rui.wei
 * @Date ：Created in 11:17 2019/4/12
 * @Description：
 */
public class DubboLogFilter implements Filter {

    private static Logger logger = LoggerFactory.getLogger(DubboLogFilter.class);

    private static final String PARAM_NAME = "arg";

    private static final String CONSUMER_LOGGER_KEY = "dubbo.accesslog.consumer";

    private static final String PROVIER_LOGGER_KEY = "dubbo.accesslog.provider";


    private static Logger consumerLog = LoggerFactory.getLogger(CONSUMER_LOGGER_KEY);

    private static Logger providerLog = LoggerFactory.getLogger(PROVIER_LOGGER_KEY);


    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        String className = invoker.getInterface().getName();
        String methodName = invocation.getMethodName();
        DubboLogBean dubboLogBean = new DubboLogBean();
        dubboLogBean.setClassName(className);
        dubboLogBean.setMethodName(methodName);

        long timeStart = System.currentTimeMillis();

        Object[] args = invocation.getArguments();
        for (int i = 0; i < args.length; i++) {
            dubboLogBean.getRequetParam().put(PARAM_NAME + i, args[i]);
        }
        Result result = invoker.invoke(invocation);
        dubboLogBean.setReponseParam(result.getValue());
        dubboLogBean.setTakeTime(System.currentTimeMillis() - timeStart);

        log(dubboLogBean);

        return result;
    }


    private void log(DubboLogBean dubboLogBean) {
        if (RpcContext.getContext().isConsumerSide()) {
            if (dubboLogBean.getTakeTime() >=500) {
                consumerLog.error("{}#{}->[time:{},requestParam:{},response:{}]",
                        dubboLogBean.getClassName(),
                        dubboLogBean.getMethodName(),
                        dubboLogBean.getTakeTime(),
                        JSON.toJSONString(dubboLogBean.getRequetParam()),
                        JSON.toJSONString(dubboLogBean.getReponseParam()));
            }
            consumerLog.info("{}#{}->[time:{},requestParam:{},response:{}]",
                    dubboLogBean.getClassName(),
                    dubboLogBean.getMethodName(),
                    dubboLogBean.getTakeTime(),
                    JSON.toJSONString(dubboLogBean.getRequetParam()),
                    JSON.toJSONString(dubboLogBean.getReponseParam()));
        } else {
            providerLog.info("{}#{}->[time:{},requestParam:{},response:{}]",
                    dubboLogBean.getClassName(),
                    dubboLogBean.getMethodName(),
                    dubboLogBean.getTakeTime(),
                    JSON.toJSONString(dubboLogBean.getRequetParam()),
                    JSON.toJSONString(dubboLogBean.getReponseParam()));
        }
    }
}
